package com.example.spring.demo.controller;


import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.spring.demo.common.error.CustomException;
import com.example.spring.demo.common.local.JwtUtil;
import com.example.spring.demo.common.local.UserContext;
import com.example.spring.demo.common.local.UserContextHolder;
import com.example.spring.demo.common.model.req.AssignParam;
import com.example.spring.demo.common.model.req.LoginParam;
import com.example.spring.demo.common.model.vo.*;
import com.example.spring.demo.common.result.Result;
import com.example.spring.demo.entity.*;
import com.example.spring.demo.service.SysMenuService;
import com.example.spring.demo.service.SysUserService;
import com.example.spring.demo.service.TokenService;
import com.example.spring.demo.service.UserMenuService;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

//控制层
@RestController
@RequestMapping("/api/sysUser")
public class SysUserController {

    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private DefaultKaptcha defaultKaptcha;
    @Autowired
    private UserMenuService userMenuService;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private TokenService tokenService;
    //增加
    @PostMapping
    public String add(@RequestBody SysUser sysUser){
        // 调用service层
        boolean temp = sysUserService.save(sysUser);
        //判断
        if(temp){
            return "添加成功!";
        }
        throw new CustomException("添加失败!");
    }
    //删除
    @DeleteMapping("/{userId}")
    public String delete(@PathVariable("userId") Integer userId){
        boolean temp = sysUserService.removeById(userId);
        if(temp){
            return "删除成功!";
        }
        throw new CustomException("删除失败!");
    }

    //修改
    @PutMapping
    public String update(@RequestBody SysUser sysUser){
        boolean temp = sysUserService.updateById(sysUser);
        if(temp){
            return "修改成功!";
        }
        throw new CustomException("修改失败!");
    }

    //查询
    @GetMapping("/getList")
    public IPage<SysUser> getList(SysUserParam param){
        //创建查询构造器
        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        if(StrUtil.isNotEmpty(param.getNickName())){
            wrapper.like("nick_name",param.getNickName());
        }
        //构造分页对象
        IPage<SysUser> page = new Page<>(param.getCurPage(),param.getPageSize());
        //查询
        return sysUserService.page(page, wrapper);
    }

    //生成验证码
    @PostMapping("/image")
    public String imageCode(HttpServletRequest request) {
        // 生成验证码文本
        String text = defaultKaptcha.createText();

        // 将验证码存入session
        HttpSession session = request.getSession();
        session.setAttribute("code", text);
        session.setMaxInactiveInterval(30 * 60); // 设置session超时时间为30分钟

        // 生成验证码图片并转换为Base64字符串
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            BufferedImage bufferedImage = defaultKaptcha.createImage(text);
            ImageIO.write(bufferedImage, "jpg", outputStream);

            Base64.Encoder encoder = Base64.getEncoder();
            String base64 = encoder.encodeToString(outputStream.toByteArray());
            return "data:image/jpeg;base64," + base64;
        } catch (IOException e) {
            throw new CustomException("验证码生成失败！", e.getMessage());
        }
    }

    //登录
    //登录
    @PostMapping("/login")
    public LoginVo login(@RequestBody LoginParam param, HttpServletRequest request){
        //获取session里面的code验证码
        HttpSession session = request.getSession();
        String code = (String)session.getAttribute("code");
        //获取前端传递过来的验证码
        String codeParam = param.getCode();
        if(StrUtil.isEmpty(code)){
            throw new CustomException("验证码过期!");
        }
        //对比验证码
        if(!codeParam.equals(code)){
            throw new CustomException("验证码错误!");
        }
        //验证用户信息
        QueryWrapper<SysUser> query = new QueryWrapper<>();
        query.lambda().eq(SysUser::getUsername,param.getUsername())
                .eq(SysUser::getPassword, DigestUtils.md5DigestAsHex(param.getPassword().getBytes()));
        SysUser user = sysUserService.getOne(query);
        if(user == null){
            throw new CustomException("用户名或者密码错误!");
        }
        if(user.getStatus().equals("1")){
            throw new CustomException("账户被停用，请联系管理员!");
        }
        //返回登录信息
        LoginVo vo = new LoginVo();
        vo.setUserId(Long.valueOf(user.getUserId()));
        vo.setNickName(user.getNickName());
        //返回用户的菜单和按钮
        List<SysMenu> menuList = null;
        //是超级管理员
        if (StrUtil.isNotEmpty(user.getIsAdmin()) && "1".equals(user.getIsAdmin())) {
            menuList = sysMenuService.list();
        } else {
            menuList = sysMenuService.getMenuByUserId(Long.valueOf(user.getUserId()));
        }
        //获取权限字段
        List<String> codeList = Optional.ofNullable(menuList).orElse(new ArrayList<>())
                .stream()
                .map(SysMenu::getCode).collect(Collectors.toList());
        //权限字段
        vo.setCodeList(codeList);
        //获取菜单
//        List<MenuVo> menuVoList = Optional.ofNullable(menuList).orElse(new ArrayList<>())
//                .stream()
//                .filter(item -> item.getType().equals("1"))
//                .map(item -> new MenuVo(item.getMenuId(), item.getTitle(), item.getPath(),
//                        item.getIcon())).collect(Collectors.toList());
        List<SysMenu> menuVoList = Optional.ofNullable(menuList).orElse(new ArrayList<>())
                .stream()
                .filter(item -> item != null &&  StrUtil.isNotEmpty(item.getType())
                        && !item.getType().equals("2")).collect(Collectors.toList());//菜单
        List<MenuVo> router = MakeMenuTree.makeRouter(menuVoList, 0L);
        //菜单
        vo.setMenuList(router);

        Map<String, Object> chaim = new HashMap<>();
        chaim.put("userId", user.getUserId());
        chaim.put("username", user.getUsername());
        chaim.put("sex", user.getSex());

        String token = JwtUtil.genToken(chaim);
        // saveToken to DB
        tokenService.saveToken(UserToken.builder()
                .userId(user.getUserId())
                .tokenKey(user.getUserId() + token)
                .token(token)
                .build());
        vo.setToken(token);
        return vo;
    }

    //分配菜单保存
    @PostMapping("/assignSave")
    public String assignSave(@RequestBody AssignParam param) {
        //判断是否是超级管理员
        SysUser user = sysUserService.getById(param.getAssId());
        if (user != null && StrUtil.isNotEmpty(user.getIsAdmin()) && user.getIsAdmin().equals("1")) {
            throw new CustomException("当前用户是超级管理员，无需分配菜单!");
        }
        userMenuService.saveMenu(param);
        return "分配菜单成功!";
    }

    //修改密码
    @PutMapping("/updatePassword")
    public String updatePassword(@RequestBody UpdatePasswordParam param){
        //验证原密码是否正确
        SysUser user = sysUserService.getById(param.getUserId());
        //原密码加密
        String oldPassword = DigestUtils.md5DigestAsHex(param.getOldPassword().getBytes());
        if(!user.getPassword().equals(oldPassword)){
            throw new CustomException("原密码不正确!");
        }
        UpdateWrapper<SysUser> query = new UpdateWrapper<>();
        query.lambda().set(SysUser::getPassword,DigestUtils.md5DigestAsHex(param.getPassword().getBytes()))
                .eq(SysUser::getUserId,param.getUserId());
        if(sysUserService.update(query)){
            return "修改成功!";
        }
        throw new CustomException("修改失败!");
    }

    //重置密码
    @PostMapping("/resetPassword")
    public String resetPassword(@RequestBody SysUser user){
        UpdateWrapper<SysUser> query = new UpdateWrapper<>();
        query.lambda().set(SysUser::getPassword,DigestUtils.md5DigestAsHex("666666".getBytes()))
                .eq(SysUser::getUserId,user.getUserId());
        if(sysUserService.update(query)){
            return "重置成功!";
        }
        throw new CustomException("重置失败!");
    }
}
